package surface;

import colour.Colour;
import bitmap.Bitmap;
import bitmap.BitmapIO;

/**
 * This is a class for storing the information about the object's diffuse,
 * reflect and colour
 * 
 * @author Administrator
 * 
 */

public class Surface {
	private double diffuse = 0;
	private double reflect = 0;
	private Colour colour;
	private String ppm;
	private int type = 1;
	private Bitmap bp;
	// justify the PPM has read in
	private boolean readOrNot;

	/**
	 * @param diffuse
	 * @param reflect
	 */
	public Surface(double diffuse, double reflect) {
		super();
		this.diffuse = diffuse;
		this.reflect = reflect;

		this.type = 0;
	}

	/**
	 * @param diffuse
	 * @param reflect
	 * @param colour
	 */
	public Surface(double diffuse, double reflect, Colour colour) {
		super();
		this.diffuse = diffuse;
		this.reflect = reflect;
		if (colour == null) {
			this.colour = new Colour(0, 0, 0);
			this.type = 0;
		} else {
			this.colour = colour;
			this.type = 1;
		}
	}

	/**
	 * @param diffuse
	 * @param reflect
	 * @param ppm
	 */
	public Surface(double diffuse, double reflect, String ppm) {
		super();
		this.diffuse = diffuse;
		this.reflect = reflect;
		if (ppm == null) {
			this.colour = new Colour(0, 0, 0);
			this.type = 0;
		} else {
			this.ppm = ppm;
			this.type = 2;
			bp = new Bitmap();
			readOrNot = false;
		}

	}

	/**
	 * get the color by the U,V. surface Type 1, get the colour directly surface
	 * Type 0, get the black point other: get colour from PPM
	 * 
	 * @param uVal
	 * @param vVal
	 * @return
	 */

	public Colour getColourIn(final double uVal, final double vVal) {
		double uValue = uVal;
		double vValue = vVal;
		Colour result;

		// to avoid the roundoff errors
		// transform the coordination to avoid the upside image
		if (vValue > 1) {
			vValue = 1.0;
		}
		if (uValue > 1) {
			uValue = 1.0;
		}
		int hVal = (int) ((1 - vValue % 1.0D) * this.getSurfaceHeight());
		if (hVal == 0) {
			hVal = 0;
		} else {
			hVal = hVal - 1;
		}
		int wVal = (int) ((uValue % 1.0D) * this.getSurfaceWidth());
		if (wVal == 0) {
			wVal = 0;
		} else {
			wVal = wVal - 1;
		}

		result = this.getPixelInPPM(hVal, wVal);

		return result;
	}

	/**
	 * @return the diffuse
	 */
	public double getDiffuse() {
		return diffuse;
	}

	/**
	 * @return the reflect
	 */
	public double getReflect() {
		
		return reflect;
	}

	/**
	 * single colour on the surface
	 * @return the colour
	 */
	public Colour getColour() {
		return colour;
	}

	public int getSurfaceWidth() {

		return bp.getWidth();
	}

	/**
	 * get the height of the surface , read the ppm when it has not done it
	 * 
	 * @return
	 */
	public int getSurfaceHeight() {
		if (!readOrNot) {
			// read from the bitmap
			BitmapIO bio = new BitmapIO();
			bp = bio.readBitmap(ppm);

			readOrNot = true;
		}
		return bp.getHeight();
	}

	/**
	 * read the PPM in the first time to use it
	 * 
	 * @return Colour
	 */
	public Colour getPixelInPPM(int i, int j) {
		if (!readOrNot) {
			BitmapIO bio = new BitmapIO();
			bp = bio.readBitmap(ppm);

			readOrNot = true;
		}
		return bp.getColourIndex(i, j);
	}

	/**
	 * @return the type
	 */
	public int getType() {
		return type;
	}
	
	

}
